﻿//!/ 20111201.1448-0800 date.js

Date.prototype.toRelativeString = function () {
    // time in milliseconds
    var oneMinute = 60 * 1000;
    var twoMinutes = oneMinute * 2;
    var fortyMinutes = 40 * oneMinute;
    var oneHour = 60 * oneMinute;
    var oneThirty = 90 * oneMinute;
    var oneDay = 24 * oneHour;
    var threeDays = oneDay * 3;

    var now = new Date();
    var timeAgo = now - this; // time in milliseconds    
    if (timeAgo < 0) {
        return "from the future";
    }
    else if (timeAgo <= twoMinutes) {
        return "about a minute ago";
    }
    else if (timeAgo <= fortyMinutes) {
        return Math.floor(timeAgo / oneMinute) + " minutes ago";
    }
    else if (timeAgo <= oneThirty) {
        return "about an hour ago";
    }
    else if (timeAgo <= oneDay) {
        return Math.ceil(timeAgo / oneHour) + " hours ago";
    }
    else if (timeAgo <= threeDays) {
        var day;
        if (now.getDay() - this.getDay() == 1) {
            day = 'Yesterday';
        }
        else {
            day = this.toDateString().slice(0, 3); // day of week
        }
        return day + ' at ' + this.toTimeCompactString();
    }
    else {
        return this.toDateTimeCompactString();
    }
};

Date.prototype.toDateTimeCompactString = function () {
    var thisYear = new Date().getFullYear();
    var date = this.toDateString();
    if (this.getFullYear() == thisYear) {
        // slice 0,-4: start at beginning of string and stop 4 off the end (i.e. cuts off the the year: 2010)
        date = date.slice(0, -4);
    }
    // Slice off day of the week
    date = date.slice(3);
    return date + ' at ' + this.toTimeCompactString();
};

Date.prototype.toTimeCompactString = function () {
    var minutes;
    var hours = this.getHours();
    var amOrPm = 'am';
    if (hours >= 12) {
        hours = hours - 12;
        amOrPm = 'pm';
    }
    if (hours === 0) {
        hours = 12;
    }
    minutes = this.getMinutes();
    if (minutes < 10) {
        minutes = '0' + minutes;
    }
    return hours + ':' + minutes + amOrPm;
};

if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {
    Date.prototype.toISOString = function toISOString() {
        var result, length, value, year;
        if (!isFinite(this)) {
            throw new RangeError;
        }
        result = [this.getUTCMonth() + 1, this.getUTCDate(),
            this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
        year = this.getUTCFullYear();
        year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6);
        length = result.length;
        while (length--) {
            value = result[length];
            if (value < 10) {
                result[length] = "0" + value;
            }
        }
        return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." + ("000" + this.getUTCMilliseconds()).slice(-3) + "Z";
    };
}

if (!Date.now) {
    Date.now = function now() {
        return new Date().getTime();
    };
}

if (!Date.prototype.toJSON) {
    Date.prototype.toJSON = function toJSON(key) {
        if (typeof this.toISOString != "function") {
            throw new TypeError();
        }
        return this.toISOString();
    };
}

if (!Date.parse || Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) {
    Date = (function (nativeDate) {
        var date1 = function (Y, M, D, h, m, s, ms) {
            var length = arguments.length;
            if (this instanceof nativeDate) {
                var date = length == 1 && String(Y) === Y ?
                    new nativeDate(date1.parse(Y)) :
                    length >= 7 ? new nativeDate(Y, M, D, h, m, s, ms) :
                    length >= 6 ? new nativeDate(Y, M, D, h, m, s) :
                    length >= 5 ? new nativeDate(Y, M, D, h, m) :
                    length >= 4 ? new nativeDate(Y, M, D, h) :
                    length >= 3 ? new nativeDate(Y, M, D) :
                    length >= 2 ? new nativeDate(Y, M) :
                    length >= 1 ? new nativeDate(Y) :
                                  new nativeDate();
                date.constructor = date1;
                return date;
            }
            return nativeDate.apply(this, arguments);
        };
        var isoDateExpression = new RegExp("^" +
            "(\\d{4}|[\+\-]\\d{6})" + 
            "(?:-(\\d{2})" + 
            "(?:-(\\d{2})" + 
            "(?:" + 
                "T(\\d{2})" + 
                ":(\\d{2})" + 
                "(?:" + 
                    ":(\\d{2})" + 
                    "(?:\\.(\\d{3}))?" + 
                ")?" +
            "(?:" + 
                "Z|" + 
                "(?:" + 
                    "([-+])" + 
                    "(\\d{2})" +
                    ":(\\d{2})" +
                ")" +
            ")?)?)?)?" +
        "$");
        for (var key in nativeDate) {
            date1[key] = nativeDate[key];
        }
        date1.now = nativeDate.now;
        date1.UTC = nativeDate.UTC;
        date1.prototype = nativeDate.prototype;
        date1.prototype.constructor = date1;
        date1.parse = function parse(string) {
            var match = isoDateExpression.exec(string);
            if (match) {
                match.shift();
                for (var i = 1; i < 7; i++) {
                    match[i] = +(match[i] || (i < 3 ? 1 : 0));
                    if (i == 1) {
                        match[i]--;
                    }
                }
                var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop();
                var offset = 0;
                if (sign) {
                    if (hourOffset > 23 || minuteOffset > 59) {
                        return NaN;
                    }
                    offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1);
                }
                var year = +match[0];
                if (0 <= year && year <= 99) {
                    match[0] = year + 400;
                    return nativeDate.UTC.apply(this, match) + offset - 12622780800000;
                }
                return nativeDate.UTC.apply(this, match) + offset;
            }
            return nativeDate.parse.apply(this, arguments);
        };

        return date1;
    })(Date);
}
